<html>
<head><meta charset="utf-8"><title>let ... else · t-lang · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/index.html">t-lang</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html">let ... else</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="228689433"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228689433" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228689433">(Mar 03 2021 at 23:42)</a>:</h4>
<p>I've been repeatedly finding cases where I'd like <code>let pat = expr else { ... }</code>. We talked about that some time ago, and it seemed like folks were in favor, modulo getting the syntax right/unambiguous.</p>



<a name="228689484"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228689484" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228689484">(Mar 03 2021 at 23:43)</a>:</h4>
<p>Other than getting the syntax right and unambiguous, were there any blockers for that?</p>



<a name="228690165"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228690165" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228690165">(Mar 03 2021 at 23:49)</a>:</h4>
<p>Not to my recollection</p>



<a name="228690212"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228690212" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228690212">(Mar 03 2021 at 23:49)</a>:</h4>
<p>I'm still not 100% confident about wanting it but I do agree it comes up a bunch</p>



<a name="228690530"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228690530" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228690530">(Mar 03 2021 at 23:52)</a>:</h4>
<p>I really often find myself writing code like <code>let x = if let Some(x) = expr { x } else { ... };</code>. That pattern seems to crop up repeatedly in many functions I write.</p>



<a name="228691667"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228691667" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228691667">(Mar 04 2021 at 00:03)</a>:</h4>
<p>"not 100% confident about wanting it" is how I would have described <code>if let</code> to begin with. However, since we have <code>if let</code> already, it seems entirely natural to extend the ability with an <code>else</code> possibility.</p>



<a name="228692193"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228692193" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228692193">(Mar 04 2021 at 00:08)</a>:</h4>
<p>I definitely hit that pattern repeatedly</p>



<a name="228692245"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228692245" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nikomatsakis <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228692245">(Mar 04 2021 at 00:09)</a>:</h4>
<p>I tend to write it with <code>match</code> but...</p>



<a name="228693508"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693508" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693508">(Mar 04 2021 at 00:21)</a>:</h4>
<p><span class="user-mention silent" data-user-id="123586">nagisa</span> said:</p>
<blockquote>
<p>requiring that the else block diverses seems… pretty weird to me. Not from the perpective of why you'd require but from the perspective of this seeming fairly constrained to add additional syntax over.</p>
</blockquote>
<p>I've seen this pattern in many, many code bases.</p>



<a name="228693631"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693631" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693631">(Mar 04 2021 at 00:22)</a>:</h4>
<p>Not just in Rust, either. It's a common pattern in other languages, too, in a different way.</p>



<a name="228693709"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693709" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693709">(Mar 04 2021 at 00:23)</a>:</h4>
<p>In Rust, though, it interacts with safety and initialization.</p>



<a name="228693774"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693774" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693774">(Mar 04 2021 at 00:24)</a>:</h4>
<p><code>if some_condition { diverge }</code> is simpler than <code>if some_condition { diverge } else { entire rest of the function }</code> (whichever order you write the two clauses in).</p>



<a name="228693857"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693857" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693857">(Mar 04 2021 at 00:25)</a>:</h4>
<p><code>if let refutable_pattern = expr { ... }</code> works great if you have something to do if the pattern matches, and then you rejoin and do the same thing either way afterward.</p>



<a name="228693904"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228693904" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228693904">(Mar 04 2021 at 00:25)</a>:</h4>
<p>It doesn't work so well if you want bindings for the variables in the refutable pattern, throughout the rest of the function.</p>



<a name="228694091"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694091" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694091">(Mar 04 2021 at 00:27)</a>:</h4>
<p>I… would still perhaps look for a way to make <code>if let</code> work for this. In my experience writhing this same code many times, I would revert to <code>match</code> primarily because with formatting people generally prefer (think: default rustfmt) <code>if let</code> in this scenario introduces many more lines.</p>



<a name="228694244"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694244" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694244">(Mar 04 2021 at 00:28)</a>:</h4>
<p>There was a great deal of discussion on this the last time it came up. One of many proposals was something like <code>if let !Some(x) = pattern { diverge }</code>, and then <code>x</code> got bound if you <em>didn't</em> enter the <code>if</code>. That seemed much less clear.</p>



<a name="228694255"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694255" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694255">(Mar 04 2021 at 00:28)</a>:</h4>
<p>So to me the issue with the <code>if let</code> in this situation is more about poor defaults. An extra name binding… I _think_ is not as big of a deal to me.</p>



<a name="228694303"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694303" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694303">(Mar 04 2021 at 00:28)</a>:</h4>
<p>Can you say more about what you mean by "poor defaults" here?</p>



<a name="228694540"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694540" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694540">(Mar 04 2021 at 00:31)</a>:</h4>
<p>/me is also trying to find the previous discussion of this.</p>



<a name="228694782"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694782" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694782">(Mar 04 2021 at 00:33)</a>:</h4>
<p>Well, like whenever I write this kind of construct I generally write this:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">apple</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"></span>
<span class="w">    </span><span class="n">_</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="k">return</span><span class="p">,</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
</code></pre></div>
<p>I do so because its fewer lines than </p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">apple</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">x</span><span class="w"></span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">return</span><span class="p">;</span><span class="w"></span>
<span class="p">};</span><span class="w"></span>
</code></pre></div>
<p>which is what rustfmt would format that statement as by default. It adds way more noise than I'd like. But its not necessarily an issue with the construct. I wouldn't mind using <code>if let</code> in this scenario if this ended up being formatted as</p>
<div class="codehilite"><pre><span></span><code>let x = if let Some(x) = apple { x } else {
    return;
}
</code></pre></div>
<p>I think _even_ with the additional binding if this kind of pattern is formatted a different way, it'd become a second nature for people to identify this pattern through how it "looks".</p>



<a name="228694968"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228694968" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228694968">(Mar 04 2021 at 00:34)</a>:</h4>
<p>It's absolutely possible to identify the pattern by looking at it. But it still feels like a "code smell". It's a pattern that indicates the need for improvement.</p>



<a name="228695038"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695038" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695038">(Mar 04 2021 at 00:35)</a>:</h4>
<p>The formatting you suggest above is an improvement, but doesn't solve the primary thing that <code>let ... else</code> does.</p>



<a name="228695039"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695039" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695039">(Mar 04 2021 at 00:35)</a>:</h4>
<p>(I also tend to introduce functions/etc and utilize <code>?</code> when this pattern repeats more than once or a twice in a function)</p>



<a name="228695065"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695065" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695065">(Mar 04 2021 at 00:35)</a>:</h4>
<p>(So perhaps <code>try {}</code> is some form of a solution there?)</p>



<a name="228695157"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695157" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695157">(Mar 04 2021 at 00:36)</a>:</h4>
<p>You still have to write <code>x</code> three times (and <code>let</code> twice), you push <code>apple</code> much further to the right (which is an issue if <code>apple</code> itself is complicated), and you push <code>Some(x)</code> into the middle of a longer expression when that pattern match is actually important.</p>



<a name="228695247"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695247" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695247">(Mar 04 2021 at 00:37)</a>:</h4>
<p>It's a recognizable pattern but an obfuscating one.</p>



<a name="228695381"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695381" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695381">(Mar 04 2021 at 00:39)</a>:</h4>
<p>I wonder how common is this pattern for types that don't implement <code>Try</code>.</p>



<a name="228695477"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695477" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695477">(Mar 04 2021 at 00:40)</a>:</h4>
<p>It applies even if the type does implement <code>Try</code>, if what you want to put in the <code>else</code> doesn't match the behavior of <code>?</code>.</p>



<a name="228695859"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695859" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695859">(Mar 04 2021 at 00:44)</a>:</h4>
<p><span class="user-mention" data-user-id="239881">@Josh Triplett</span> is there a reason the else has to diverge in the case you're bringing up? It feels like an unnecessary restriction to me, the <code>let pat = expr else { ... };</code> isn't just sugar then.</p>



<a name="228695881"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695881" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695881">(Mar 04 2021 at 00:44)</a>:</h4>
<p><span class="user-mention silent" data-user-id="116122">simulacrum</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228695859">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="239881">Josh Triplett</span> is there a reason the else has to diverge in the case you're bringing up? It feels like an unnecessary restriction to me, the <code>let pat = expr else { ... };</code> isn't just sugar then.</p>
</blockquote>
<p>Because if it doesn't diverge, it'd continue into the containing block without binding the values in <code>pat</code>.</p>



<a name="228695941"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695941" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695941">(Mar 04 2021 at 00:45)</a>:</h4>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">expr</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="fm">println!</span><span class="p">(</span><span class="s">"huh, it didn't match"</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
<span class="c1">// What is x now?</span>
</code></pre></div>



<a name="228695945"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695945" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695945">(Mar 04 2021 at 00:45)</a>:</h4>
<p>No, I mean, it can be sugar for <code>let binding = if let pat = expr { binding } else { ... }</code></p>



<a name="228695959"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228695959" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228695959">(Mar 04 2021 at 00:45)</a>:</h4>
<p>Right?</p>



<a name="228696020"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696020" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696020">(Mar 04 2021 at 00:46)</a>:</h4>
<p>If you don't diverge you need ... to also have the same type as binding</p>



<a name="228696041"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696041" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696041">(Mar 04 2021 at 00:46)</a>:</h4>
<p>So your example would be "just" a type error</p>



<a name="228696050"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696050" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696050">(Mar 04 2021 at 00:46)</a>:</h4>
<p>I see.</p>



<a name="228696083"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696083" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696083">(Mar 04 2021 at 00:47)</a>:</h4>
<p>That'd be a more complex desugaring, and we'd have to specify exactly how you provide a set of bindings, but it could theoretically work.</p>



<a name="228696143"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696143" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696143">(Mar 04 2021 at 00:47)</a>:</h4>
<p>Are you proposing <code>let Some(x) = expr else { Some(42) }</code> or <code>let Some(x) = expr else { 42 }</code>?</p>



<a name="228696158"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696158" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696158">(Mar 04 2021 at 00:47)</a>:</h4>
<p>/me steps away for a bit, but will be back later this evening.</p>



<a name="228696292"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696292" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696292">(Mar 04 2021 at 00:49)</a>:</h4>
<p>Hm. I think it has to be the latter, otherwise you still need to confirm the match. Presumably we would only support single-variable bindings to start.</p>



<a name="228696333"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696333" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696333">(Mar 04 2021 at 00:49)</a>:</h4>
<p>This is perhaps better exemplified by having more complicated bindings than just <code>Some(x)</code>. What about, say <code>let Enum::Variant { foo, bar, baz, .. }</code> = ... else { ??? }`?</p>



<a name="228696478"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696478" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696478">(Mar 04 2021 at 00:50)</a>:</h4>
<p>Exactly.</p>



<a name="228696510"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696510" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> nagisa <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696510">(Mar 04 2021 at 00:51)</a>:</h4>
<p>To me it seems like if we're implementing something like this, requiring divergence is a significantly safer choice than limiting this to single-variable bindings.</p>



<a name="228696511"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696511" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696511">(Mar 04 2021 at 00:51)</a>:</h4>
<p>That complexity, together with the lack of a need for a non-diverging else case in the primary use case, is the reason why all the proposals I've seen have required a diverging else.</p>



<a name="228696887"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228696887" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> simulacrum <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228696887">(Mar 04 2021 at 00:55)</a>:</h4>
<p>It seems OK to require it to diverge, though it definitely feels "more weird" to me at first glance, though it certainly has good reasons for that limitation. It's forwards compatible too, I think, with future extensions.</p>



<a name="228699019"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228699019" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228699019">(Mar 04 2021 at 01:14)</a>:</h4>
<p><span class="user-mention silent" data-user-id="123586">nagisa</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228695381">said</a>:</p>
<blockquote>
<p>I wonder how common is this pattern for types that don't implement <code>Try</code>.</p>
</blockquote>
<p>As I recall this is highly common in clippy, and such, where it's looking for specific patterns and wants to <code>continue</code>/etc if it's not that patterns, but it's in complex AST types, not <code>Try</code> types.</p>



<a name="228699579"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228699579" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228699579">(Mar 04 2021 at 01:19)</a>:</h4>
<p>That said, I do think it would be nice to have a special syntax for try-like types, so that something like <code>let x = my_opt ☃ foo() ☃ 4;</code> could work.  (Like <code>?</code> or <code>??</code> in <code>C#</code>.)</p>
<p>But that's a different thing from <code>let else</code>, so I guess I shouldn't talk about it.</p>



<a name="228710540"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228710540" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228710540">(Mar 04 2021 at 03:31)</a>:</h4>
<p><span class="user-mention" data-user-id="125270">@scottmcm</span> I think that's just unwrap_or_else or map_or or similar; that one is easier to solve with combinators.</p>



<a name="228716223"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716223" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716223">(Mar 04 2021 at 04:43)</a>:</h4>
<p>I think <code>if !let Some(x) = apple { diverge }</code> makes more sense than <code>if let !Some(x) = apple { diverge }</code>, although perhaps you don't like either option. It makes more sense if <code>if let pat1 = ... &amp;&amp; let pat2 = ...</code> for if-chain is approved. Personally I would be really happy to see any form of this land</p>



<a name="228716373"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716373" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> isHavvy <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716373">(Mar 04 2021 at 04:45)</a>:</h4>
<p>If we ever added structural record types (a.k.a. anonymous structs), it would allow us to not force divergence in the else case. But without that, and without a sufficiently-motivated use-case...</p>



<a name="228716404"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716404" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716404">(Mar 04 2021 at 04:45)</a>:</h4>
<p>I actually have a macro for this pattern in my project</p>



<a name="228716481"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716481" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> isHavvy <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716481">(Mar 04 2021 at 04:46)</a>:</h4>
<p>Link?</p>



<a name="228716590"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716590" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716590">(Mar 04 2021 at 04:47)</a>:</h4>
<p><a href="https://github.com/digama0/mm0/blob/0ba34ef477b7b8d0f94e250ca338b32eb33034b5/mm0-rs/components/mm0_util/src/lib.rs#L118-L143">https://github.com/digama0/mm0/blob/0ba34ef477b7b8d0f94e250ca338b32eb33034b5/mm0-rs/components/mm0_util/src/lib.rs#L118-L143</a></p>



<a name="228716663"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716663" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716663">(Mar 04 2021 at 04:48)</a>:</h4>
<p>It's specialized to the case <code>diverge = std::hint::unreachable_unchecked()</code> but I've been thinking about extending it to other kinds of divergence</p>



<a name="228716819"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228716819" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228716819">(Mar 04 2021 at 04:50)</a>:</h4>
<p>This is just a simple <code>macro_rules</code> macro, but with a procedural macro you can automatically construct the binding pattern from the refutable pattern, so that the <code>else</code> doesn't have to diverge and instead returns a tuple of the bindings</p>



<a name="228722973"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228722973" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228722973">(Mar 04 2021 at 06:11)</a>:</h4>
<p><span class="user-mention silent" data-user-id="239881">Josh Triplett</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228710540">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> I think that's just unwrap_or_else or map_or or similar; that one is easier to solve with combinators.</p>
</blockquote>
<p>Depends, as usual, whether it's <code>let x = foo ☃ bar().await?;</code>.  (I don't currently use async.await in Rust, but in C# I've had that kind of thing before.)</p>



<a name="228723652"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228723652" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228723652">(Mar 04 2021 at 06:21)</a>:</h4>
<p>What are the types there? I would guess that <code>foo?.bar().await?;</code> or <code>foo.and_then(|foo| foo.bar())?.await?;</code> or similar would work</p>



<a name="228729390"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228729390" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228729390">(Mar 04 2021 at 07:39)</a>:</h4>
<p>What if the <code>else</code> block had the same declared bindings, just not initialized yet, so you could assign them?</p>
<div class="codehilite"><pre><span></span><code>let Some(Foo { x, y }) = foo() else {
    x = 1;
    y = 2;
};
</code></pre></div>
<p>If you don't assign all bindings in the pattern, the rest will be unusable later, just there for conditional drop I guess. Or if you diverge, that's fine too.</p>



<a name="228729691"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228729691" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228729691">(Mar 04 2021 at 07:42)</a>:</h4>
<p>As if:</p>
<div class="codehilite"><pre><span></span><code>let (x, y);
if let Some(Foo { x: pat_x, y: pat_y }) = foo() {
    x = pat_x;
    y = pat_y;
} else {
    x = 1;
    y = 2;
}
</code></pre></div>



<a name="228735698"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228735698" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228735698">(Mar 04 2021 at 08:42)</a>:</h4>
<p><span class="user-mention" data-user-id="138448">@cuviper</span> That seems reasonable as an alternative, sure.</p>



<a name="228762376"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228762376" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dirkjan Ochtman <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228762376">(Mar 04 2021 at 12:22)</a>:</h4>
<p>I definitely badly want this; I write <code>match foo { Some(x) =&gt; x, None =&gt; diverge() }</code> really <em>all</em> the time</p>



<a name="228789598"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228789598" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228789598">(Mar 04 2021 at 15:16)</a>:</h4>
<p>(see also <a href="https://github.com/rust-lang/rfcs/issues/2616">https://github.com/rust-lang/rfcs/issues/2616</a>)</p>



<a name="228829697"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228829697" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228829697">(Mar 04 2021 at 18:56)</a>:</h4>
<p><span class="user-mention silent" data-user-id="138448">cuviper</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228729390">said</a>:</p>
<blockquote>
<p>What if the <code>else</code> block had the same declared bindings, just not initialized yet, so you could assign them?</p>
</blockquote>
<p>That's really clever!  I don't remember it having been raised in any of the previous conversations, either.</p>



<a name="228830792"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228830792" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228830792">(Mar 04 2021 at 19:03)</a>:</h4>
<p>My usual comment when "block that must be <code>-&gt; !</code> comes up":</p>
<p>That could also be a reason to have <code>unless</code>.  It's questionably useful in most languages, where <code>unless A</code> is just <code>if !(A)</code>.  But with better type requirements, it would allow the reader to concentrate on the "what requirement is being upheld after this", since they have a language guarantee that control flow <em>cannot</em> resume after the block.</p>
<p>And the inverted phrasing is most useful for that, which is why it's <code>assert!(a &gt; 0)</code> not <code>panic_if!(a &lt;= 0)</code> -- <code>assert!(a)</code> is <code>unless a { panic!() }</code>.</p>
<p>So that would make it the "clearly doing precondition checks" form -- <code>unless i % 4 == 0 { continue }</code> in loops, etc.  And <code>unless let Some(x) = x { panic() }</code> for <code>unwrap</code>.</p>
<p>(But historically people haven't liked the idea.)</p>



<a name="228835533"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228835533" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228835533">(Mar 04 2021 at 19:32)</a>:</h4>
<p>I can see why a general <code>unless</code> may not be well received, but I have to admit that <code>unless let Some(x) = fallible() { return; }</code> looks quite nice.</p>
<p>A mention a bit tangentially related to <code>let … else</code> are <code>in patterns</code>, which may be especially interesting if considering a non-diverging else path, is <code>in</code> patterns. Taking <span class="user-mention" data-user-id="138448">@cuviper</span>'s example:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">);</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">z</span>: <span class="nc">in</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="p">})</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">42</span><span class="p">;</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">27</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="c1">// or</span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="p">(</span><span class="mi">42</span><span class="p">,</span><span class="w"> </span><span class="mi">27</span><span class="p">);</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<ul>
<li>Incidentally, this would make Rust become Python: <code>let (in x, in y) = (y, x);</code> <span aria-label="big smile" class="emoji emoji-1f604" role="img" title="big smile">:big_smile:</span></li>
</ul>



<a name="228835977"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228835977" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228835977">(Mar 04 2021 at 19:34)</a>:</h4>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228830792">said</a>:</p>
<blockquote>
<p>So that would make it the "clearly doing precondition checks" form -- <code>unless i % 4 == 0 { continue }</code> in loops, etc.  And <code>unless let Some(x) = x { panic() }</code> for <code>unwrap</code>.</p>
<p>(But historically people haven't liked the idea.)</p>
</blockquote>
<p>I don't like <code>unless</code> non-historically <span aria-label="smile" class="emoji emoji-1f642" role="img" title="smile">:smile:</span> </p>
<p>but it reads much more naturally in the form of Swift's <code>guard i % 4 == 0 else { continue }</code>, the <code>else</code> being the important separator.</p>



<a name="228836215"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228836215" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228836215">(Mar 04 2021 at 19:36)</a>:</h4>
<p><span class="user-mention" data-user-id="232018">@Daniel Henry-Mantilla</span> I think <a href="https://rust-lang.github.io/rfcs/2909-destructuring-assignment.html">destructuring assigment</a> will cover that<br>
but I suppose <code>in</code>-patterns would let you mix new and existing bindings</p>



<a name="228837093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228837093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Daniel Henry-Mantilla <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228837093">(Mar 04 2021 at 19:42)</a>:</h4>
<p>True! Although that RFC comes with:</p>
<blockquote>
<p>Patterns must be irrefutable.</p>
</blockquote>
<p>Which to me, is a bigger annoyance than having to type that <code>in</code> keyword, since I was also thinking of being able to use it with <code>match</code> arms (I hate having to do <code>Pattern { x: x_, … } =&gt; { x = x_;  … },</code>).<br>
For the irrefutable pattern kind of case, however, having that <code>let</code> seems a bit useless, so I wouldn't even mind having both options around. But should there be only one such feature, <code>in</code> being a more flexible tool is an important thing to keep in mind.</p>



<a name="228837692"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228837692" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228837692">(Mar 04 2021 at 19:46)</a>:</h4>
<p>hmm, that might improve my <code>let</code>-<code>else</code> desugaring too<br>
(edit: oh wow, I missed that you literally spelled that out before)</p>



<a name="228839325"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228839325" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228839325">(Mar 04 2021 at 19:56)</a>:</h4>
<p>I had only noticed what you wrote in the <code>else</code> block before</p>



<a name="228839488"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228839488" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228839488">(Mar 04 2021 at 19:56)</a>:</h4>
<p>idk it feels quite ...wrong?... when a pattern is "impure", like will there be any problem with</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="k">mut</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="nb">String</span>::<span class="n">new</span><span class="p">();</span><span class="w"></span>
<span class="k">match</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nb">Some</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="fm">dbg!</span><span class="p">(</span><span class="o">&amp;</span><span class="k">mut</span><span class="w"> </span><span class="n">x</span><span class="p">).</span><span class="n">is_empty</span><span class="p">()</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kc">false</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">{}</span><span class="w"></span>
<span class="w">                          </span><span class="c1">//^ should it point to the outside `x`, or `foo`</span>
</code></pre></div>



<a name="228840068"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228840068" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228840068">(Mar 04 2021 at 19:59)</a>:</h4>
<p>by scoping it would have to be the one inside <code>foo</code>, which would be a borrowck error since you don't get mutable access in the guard</p>



<a name="228840314"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228840314" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228840314">(Mar 04 2021 at 20:00)</a>:</h4>
<p>but assuming you could observe it (a little difficult because of name shadowing), the guard should see the old value of the shadowed variable, and the assignment to the variable happens after the guard but before any code in the branch</p>



<a name="228840403"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228840403" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228840403">(Mar 04 2021 at 20:01)</a>:</h4>
<p>(That said this is just a rule I made up; I guess your point is that the rule may not be obvious)</p>



<a name="228841506"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228841506" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228841506">(Mar 04 2021 at 20:08)</a>:</h4>
<p>lemme see. in the case of <code>if let</code> chain (<a href="https://github.com/rust-lang/rfcs/issues/2497">rfc#2497</a>), the assignment happens after the full chain</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">if</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="o">&amp;&amp;</span><span class="w"> </span><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// x, y reassigned here</span>
<span class="p">}</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// x, y keeps original value</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p><code>in</code> is disallowed in function params</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">|</span><span class="k">in</span><span class="w"> </span><span class="n">z</span><span class="o">|</span><span class="w"> </span><span class="n">z</span><span class="p">;</span><span class="w"></span>
<span class="c1">//       ^~~~ throw error i suppose</span>
</code></pre></div>
<p>allowed in <code>for</code> loop</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">for</span><span class="w"> </span><span class="p">(</span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">y</span><span class="p">)</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">arr</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// x, y reassigned every loop</span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="228843036"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228843036" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228843036">(Mar 04 2021 at 20:18)</a>:</h4>
<p>I don't know if it's advisable, but there's a perfectly valid desugaring of <code>in</code> in function params:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">z</span><span class="p">;</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">|</span><span class="k">in</span><span class="w"> </span><span class="n">z</span><span class="o">|</span><span class="w"> </span><span class="n">z</span><span class="p">;</span><span class="w"></span>
</code></pre></div>
<p>=</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">z</span><span class="p">;</span><span class="w"></span>
<span class="kd">let</span><span class="w"> </span><span class="n">g</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="o">|</span><span class="n">z_</span><span class="o">|</span><span class="w"> </span><span class="p">{</span><span class="n">z</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">z_</span><span class="p">;</span><span class="w"> </span><span class="n">z</span><span class="p">};</span><span class="w"></span>
</code></pre></div>



<a name="228843528"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228843528" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228843528">(Mar 04 2021 at 20:22)</a>:</h4>
<p>yeah.</p>



<a name="228843864"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228843864" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> kennytm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228843864">(Mar 04 2021 at 20:23)</a>:</h4>
<p>so now you get</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">y</span><span class="p">);</span><span class="w"></span>
<span class="k">if</span><span class="w"> </span><span class="o">!</span><span class="fm">matches!</span><span class="p">(</span><span class="n">foo</span><span class="p">(),</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">Foo</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">in</span><span class="w"> </span><span class="n">x</span><span class="p">,</span><span class="w"> </span><span class="n">z</span>: <span class="nc">in</span><span class="w"> </span><span class="n">y</span><span class="w"> </span><span class="p">}))</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="k">break</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="228845567"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228845567" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228845567">(Mar 04 2021 at 20:33)</a>:</h4>
<p>Now that's an idiom that will take some getting used to</p>



<a name="228845929"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228845929" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228845929">(Mar 04 2021 at 20:35)</a>:</h4>
<p>Unfortunately I don't think it will work as "let ... else" because rust doesn't support initialization checking via boolean control flow; you would have to rewrite the match inside the <code>matches!</code> so that the false branches are <code>break</code></p>



<a name="228857664"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228857664" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228857664">(Mar 04 2021 at 21:56)</a>:</h4>
<p><span class="user-mention" data-user-id="125270">@scottmcm</span> I can't say I'm a fan of <code>unless</code> in general, but I'll admit that <code>unless let Some(x) = ... { diverge }</code> is nicer than <code>if !let Some(x) = ... { diverge }</code>. But I feel like both of them are a little harder to mentally parse than <code>let Some(x) = ... else</code>. Specifically, I feel like it needs to be obvious that "this binds x", so the important thing to "lead with" is "let", not "if" or "unless".</p>



<a name="228857757"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228857757" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228857757">(Mar 04 2021 at 21:57)</a>:</h4>
<p>Mental parser: "What kind of statement is this? Ah, it's a let; it's binding something. Oh, that's a refutable pattern. And there's the <code>else</code> for if it doesn't match..."</p>



<a name="228857891"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228857891" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228857891">(Mar 04 2021 at 21:58)</a>:</h4>
<p>That's doubly true if you're scanning <em>upwards</em> from a use of <code>x</code> later in the function to see where <code>x</code> is assigned/bound.</p>



<a name="228858574"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228858574" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228858574">(Mar 04 2021 at 22:02)</a>:</h4>
<p>I can mention, as prior art, that in Lean (a functional programming language) inside monadic do blocks you can assign a variable with</p>
<div class="codehilite" data-code-language="Lean"><pre><span></span><code><span class="k">do</span>
<span class="bp">...</span>
<span class="n">a</span> <span class="bp">&lt;-</span> <span class="o">(</span><span class="n">ma</span> <span class="o">:</span> <span class="n">m</span> <span class="n">A</span><span class="o">),</span>
<span class="bp">...</span>
</code></pre></div>
<p>and you can use an irrefutable pattern there:</p>
<div class="codehilite" data-code-language="Lean"><pre><span></span><code><span class="k">do</span>
<span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="bp">&lt;-</span> <span class="o">(</span><span class="n">mab</span> <span class="o">:</span> <span class="n">m</span> <span class="o">(</span><span class="n">A</span> <span class="n">x</span> <span class="n">B</span><span class="o">)),</span>
<span class="bp">...</span>
</code></pre></div>
<p>as well as a refutable pattern, provided the monad is alternative or you provide an "else" case:</p>
<div class="codehilite" data-code-language="Lean"><pre><span></span><code><span class="k">do</span>
<span class="n">some</span> <span class="o">(</span><span class="n">a</span><span class="o">,</span> <span class="n">b</span><span class="o">)</span> <span class="bp">&lt;-</span> <span class="o">(</span><span class="n">mab</span> <span class="o">:</span> <span class="n">m</span> <span class="o">(</span><span class="n">option</span> <span class="o">(</span><span class="n">A</span> <span class="n">x</span> <span class="n">B</span><span class="o">)))</span> <span class="bp">|</span> <span class="o">(</span><span class="n">mr</span> <span class="o">:</span> <span class="n">m</span> <span class="n">R</span><span class="o">),</span>
</code></pre></div>
<p>where <code>R</code> is the return value of the whole block (so this would be something like <code>return</code> or <code>break 'a</code> in rust). I'm pretty sure this is cribbed from haskell, like the rest of do notation.</p>



<a name="228863661"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228863661" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228863661">(Mar 04 2021 at 22:39)</a>:</h4>
<p><span class="user-mention silent" data-user-id="239881">Josh Triplett</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/228857757">said</a>:</p>
<blockquote>
<p>Mental parser: "What kind of statement is this? Ah, it's a let; it's binding something. Oh, that's a refutable pattern. And there's the <code>else</code> for if it doesn't match..."</p>
</blockquote>
<p>I think it can also go poorly in a mental parser, though: "What kind of statement is this? Ah, it's a let, so it's irrefutable.  Wait, why is the <code>Ok(v)</code> irrefutable?  Is the error type <code>!</code>?  Oh, wait, there's an <code>else</code>, never mind."</p>
<p>Rust is usually pretty good about not having "common prefix" syntax.</p>



<a name="228870013"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/228870013" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#228870013">(Mar 04 2021 at 23:35)</a>:</h4>
<p><span class="user-mention" data-user-id="125270">@scottmcm</span> Fair.</p>



<a name="229014382"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229014382" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dirkjan Ochtman <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229014382">(Mar 05 2021 at 19:54)</a>:</h4>
<p>Maybe <code>if not let</code>?</p>



<a name="229097007"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229097007" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dirkjan Ochtman <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229097007">(Mar 06 2021 at 13:13)</a>:</h4>
<p>I guess it's not that different from/better than <code>if !let</code></p>



<a name="229197335"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229197335" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229197335">(Mar 07 2021 at 15:52)</a>:</h4>
<p><code>if !let</code> opens weird questions about <code>if</code>-<code>else</code> chains, like the scoping for <code>if cond {} else if !let ...</code></p>



<a name="229197385"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229197385" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229197385">(Mar 07 2021 at 15:53)</a>:</h4>
<p>Maybe that's just not allowed, but then it makes an exception, that only <em>some</em> kinds of <code>else if</code> are allowed</p>



<a name="229198045"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198045" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198045">(Mar 07 2021 at 16:02)</a>:</h4>
<p>I think <code>if !let</code> only has weird scoping in the case where there is no fallback clause. If, for consistency, there is also a two-sided <code>if !let</code> then logically it should just be <code>if let</code> with the branches swapped</p>



<a name="229198065"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198065" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198065">(Mar 07 2021 at 16:02)</a>:</h4>
<p>I like that leading with <code>let</code> means that <code>let ... else</code> is introducing bindings in the current scope, like any other <code>let</code>. And the idea that the <code>else</code> can have the same (uninitialized) bindings means that it's naturally sharing the parent scope -- only the initialization is conditional, if the pattern is refuted.</p>



<a name="229198193"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198193" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198193">(Mar 07 2021 at 16:05)</a>:</h4>
<p><span class="user-mention" data-user-id="271719">@Mario Carneiro</span> you're saying that <code>if !let</code> would have an <code>else</code> with the bindings? But I think the whole idea is supposed to add bindings to the parent scope.</p>



<a name="229198211"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198211" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198211">(Mar 07 2021 at 16:05)</a>:</h4>
<p>Oh, but then <code>if cond {} else if !let pat = x {}</code> never binds <code>pat</code> - the bindings only last until the end of the <code>if !let pat = x {}</code> block which ends immediately because it is the <code>else</code> branch of a conditional</p>



<a name="229198238"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198238" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198238">(Mar 07 2021 at 16:05)</a>:</h4>
<p>yeah that's weird and useless</p>



<a name="229198312"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229198312" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229198312">(Mar 07 2021 at 16:06)</a>:</h4>
<p>Right</p>



<a name="229207330"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229207330" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229207330">(Mar 07 2021 at 18:25)</a>:</h4>
<p>I'm liking the "can assign to the same bindings in the else" approach. I still think the first version of this should just require divergence, but that no longer seems like a hard requirement for all future versions.</p>



<a name="229215520"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229215520" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229215520">(Mar 07 2021 at 20:28)</a>:</h4>
<p>Hmm, would</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="fm">unreachable!</span><span class="p">()</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>be Rust's first shift-reduce conflict?  Or are there other ones already in similarly-contrived cases?</p>



<a name="229215960"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229215960" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229215960">(Mar 07 2021 at 20:35)</a>:</h4>
<p><span class="user-mention silent" data-user-id="125270">scottmcm</span> <a href="#narrow/stream/213817-t-lang/topic/Is.20the.20.60if.60.20in.20.60else.20if.60.20part.20of.20the.20first.20.60if.60.3F/near/229215520">said</a>:</p>
<blockquote>
<p>Hmm, would</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="p">()</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="n">foo</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="k">return</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
<span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="fm">unreachable!</span><span class="p">()</span><span class="w"> </span><span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>be Rust's first shift-reduce conflict?  Or are there other ones already in similarly-contrived cases?</p>
</blockquote>
<p>Are you talking about <code>let ... else</code> there, or is there something else going on in that expression?</p>



<a name="229216360"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216360" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216360">(Mar 07 2021 at 20:42)</a>:</h4>
<p>Oops, didn't notice that the thread was about <code>else if</code>, and wasn't the <code>let ...else</code> thread.  Yeah, I meant the "does the else go with the if or the let".  I'll see if I can move the messages...</p>



<a name="229216545"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216545" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216545">(Mar 07 2021 at 20:45)</a>:</h4>
<p>(There, magically "fixed".)</p>



<a name="229216617"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216617" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216617">(Mar 07 2021 at 20:46)</a>:</h4>
<p>I think you can count <code>{ {} &amp;&amp; false }</code> as a shift reduce conflict; there are some messy disambiguation rules in the code for this</p>



<a name="229216631"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216631" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216631">(Mar 07 2021 at 20:46)</a>:</h4>
<p>Ah, because of all the "does a block need a semicolon" magic?</p>



<a name="229216633"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216633" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216633">(Mar 07 2021 at 20:46)</a>:</h4>
<p><span aria-label="+1" class="emoji emoji-1f44d" role="img" title="+1">:+1:</span></p>



<a name="229216762"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216762" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216762">(Mar 07 2021 at 20:48)</a>:</h4>
<p>Crazy idea: <code>let { pat = val } else { diverge }</code></p>



<a name="229216789"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216789" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216789">(Mar 07 2021 at 20:49)</a>:</h4>
<p>Also, the issue of <code>let ... else</code> with type <code>()</code> came up in previous discussions about <code>let ... else</code>, and the general conclusion was to just pick a direction to resolve it and not worry about it because in practice code using <code>let () = if</code> doesn't show up in the wild in ways that would break.</p>



<a name="229216804"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216804" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216804">(Mar 07 2021 at 20:49)</a>:</h4>
<p>what's the issue with type <code>()</code>?</p>



<a name="229216897"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216897" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216897">(Mar 07 2021 at 20:50)</a>:</h4>
<p>I assume that <code>let () = val else { bla }</code> isn't valid (or would be linted against?) because the pattern is irrefutable so the else block is unreachable</p>



<a name="229216926"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229216926" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229216926">(Mar 07 2021 at 20:51)</a>:</h4>
<p>It'd potentially be an issue at parse time (before we got as far as "is this pattern refutable"), because of the ambiguity Scott mentioned above.</p>



<a name="229217013"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229217013" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229217013">(Mar 07 2021 at 20:52)</a>:</h4>
<p>That ambiguity can just be resolved in favor of "match the if with the else", and if someone <em>really</em> wants the alternative (which as you observed would trigger a message about the refutable pattern) they can parenthesize the <code>if</code>:<br>
<code>let () = (if ...) else { this is unreachable }</code>.</p>



<a name="229217353"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229217353" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229217353">(Mar 07 2021 at 20:59)</a>:</h4>
<p>It does feel like we have a bunch of "expression because match arms and such, not because anyone ever really cares" cases.</p>
<p>Probably not worth moving all those things in the grammar, but surprisingly we don't even seem to lint about them:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="k">fn</span> <span class="nf">main</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">foo</span><span class="p">(</span><span class="k">if</span><span class="w"> </span><span class="n">pred</span><span class="p">()</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">bar</span><span class="p">()</span><span class="w"> </span><span class="p">});</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>compiles <a href="https://play.rust-lang.org/?version=nightly&amp;mode=debug&amp;edition=2018&amp;gist=7f6ab60cfa2739526ae48497da3b2272">without complaint</a>.</p>



<a name="229217560"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229217560" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229217560">(Mar 07 2021 at 21:02)</a>:</h4>
<p>what's wrong with that? I'm sure I've written code like that</p>



<a name="229217651"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229217651" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229217651">(Mar 07 2021 at 21:03)</a>:</h4>
<p>I've started using clippy and it gets hissy about passing units generated in "interesting" ways to a function, but it's a nice way to compress statements, especially if that's a closure</p>



<a name="229218691"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229218691" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229218691">(Mar 07 2021 at 21:19)</a>:</h4>
<p><span class="user-mention" data-user-id="125270">@scottmcm</span> I don't feel like <code>if</code> without <code>else</code> having type <code>()</code> is just for match arms; I think it's part of the general Rust property that there's no such thing as a statement, only an expression of type <code>()</code>.</p>



<a name="229218750"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229218750" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229218750">(Mar 07 2021 at 21:20)</a>:</h4>
<p>(There are exceptions, namely defining an item. But still.)</p>



<a name="229218760"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229218760" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229218760">(Mar 07 2021 at 21:20)</a>:</h4>
<p>and <code>let</code></p>



<a name="229218967"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229218967" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229218967">(Mar 07 2021 at 21:23)</a>:</h4>
<p><span class="user-mention" data-user-id="239881">@Josh Triplett</span> I mention match arms as the one place that comes to mind for me where assignment, for example, being a statement instead of an expression matters (as it allows <code>=&gt; a = b,</code> instead of needing <code>=&gt; { a = b; }</code>).</p>



<a name="229221395"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221395" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221395">(Mar 07 2021 at 22:03)</a>:</h4>
<p><span class="user-mention" data-user-id="239881">@Josh Triplett</span> we do need to decide whether the new bindings are visible in <code>else</code>, even if it's required to diverge, because of shadowing.</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="n">x</span>: <span class="nb">Option</span><span class="o">&lt;</span><span class="n">T</span><span class="o">&gt;</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="p">();</span><span class="w"></span>
<span class="c1">// ...</span>
<span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">x</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">x</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="c1">// Does this see `None`, or the new uninitialized binding?</span>
<span class="w">    </span><span class="k">return</span><span class="w"> </span><span class="n">x</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="229221456"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221456" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221456">(Mar 07 2021 at 22:04)</a>:</h4>
<p><span class="user-mention" data-user-id="138448">@cuviper</span> Oh, interesting.</p>



<a name="229221468"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221468" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221468">(Mar 07 2021 at 22:04)</a>:</h4>
<p>If it saw the new uninitialized binding it would need to fail to compile, presumably.</p>



<a name="229221477"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221477" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221477">(Mar 07 2021 at 22:05)</a>:</h4>
<p>Yes</p>



<a name="229221482"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221482" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221482">(Mar 07 2021 at 22:05)</a>:</h4>
<p>And good example, because I'd expect <code>let Some(name) = name else { ... }</code> to be a very common pattern for "refinement".</p>



<a name="229221551"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221551" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221551">(Mar 07 2021 at 22:06)</a>:</h4>
<p>At first glance, that pattern makes me inclined towards "no, they shouldn't be visible", because it seems entirely reasonable to be able to access the pre-refinement value inside the else.</p>



<a name="229221713"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221713" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221713">(Mar 07 2021 at 22:08)</a>:</h4>
<p>Well, the shadowing doesn't even have to be that immediate. It could have been something separate that was shadowed.</p>



<a name="229221731"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221731" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221731">(Mar 07 2021 at 22:08)</a>:</h4>
<p>Sure, but I think the refinement case is likely to be common.</p>



<a name="229221764"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221764" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221764">(Mar 07 2021 at 22:09)</a>:</h4>
<p>Your idea that the new uninitialized binding could be visible and assigned to does make sense, if we want to allow non-diverging <code>else</code>.</p>
<p>So I think this now becomes a question of which we'd expect to be more common: diverging else that may want to use the non-refined value (e.g. to include it or a formatted version of it in an error), or non-diverging else that wants to initialize the value in a different way in the else.</p>



<a name="229221787"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221787" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221787">(Mar 07 2021 at 22:09)</a>:</h4>
<p>Either way, one of those two will become more difficult to write.</p>



<a name="229221788"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221788" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221788">(Mar 07 2021 at 22:09)</a>:</h4>
<p>I think you just shouldn't shadow if that's what you need, or you can use a full <code>match</code>.</p>



<a name="229221874"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221874" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221874">(Mar 07 2021 at 22:10)</a>:</h4>
<p>For the sake of completeness, I'll point out that there's a "choose not to decide" choice here: we could error on any reference to the new binding from within the <code>else</code>, even if there's a shadowed binding in scope, which would be forward-compatible with either option. I don't necessarily think that's a good idea, but it seems worth mentioning.</p>



<a name="229221896"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221896" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221896">(Mar 07 2021 at 22:10)</a>:</h4>
<p>Erroring like that <em>might</em> be a good idea if we think people will find such code confusing or ambiguous to read.</p>



<a name="229221905"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221905" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> cuviper <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221905">(Mar 07 2021 at 22:10)</a>:</h4>
<p>I guess the non-diverging use could <code>match</code> too</p>



<a name="229221907"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221907" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221907">(Mar 07 2021 at 22:11)</a>:</h4>
<p>Right.</p>



<a name="229221955"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229221955" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229221955">(Mar 07 2021 at 22:11)</a>:</h4>
<p>Why don't we write two sensible examples, one for each, and see how they'd look depending on which way we go?</p>



<a name="229222044"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229222044" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229222044">(Mar 07 2021 at 22:12)</a>:</h4>
<p><span class="user-mention silent" data-user-id="138448">cuviper</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/229221905">said</a>:</p>
<blockquote>
<p>I guess the non-diverging use could <code>match</code> too</p>
</blockquote>
<p>I also suspect the non-diverging case could potentially use <code>unwrap_or</code> or <code>unwrap_or_else</code>, frequently.</p>



<a name="229222446"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229222446" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229222446">(Mar 07 2021 at 22:18)</a>:</h4>
<p>Diverging case that benefits from referencing the pre-refinement binding:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">num</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">u64</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"> </span><span class="n">fatal_parse_error</span><span class="o">!</span><span class="p">(</span><span class="s">"Failed to parse number: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">n</span><span class="p">)</span><span class="w"> </span><span class="p">};</span><span class="w"></span>
</code></pre></div>
<p>Non-diverging case that benefits from assigning to the new binding:</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nb">Some</span><span class="p">(</span><span class="n">num</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">token</span><span class="p">.</span><span class="n">parse</span>::<span class="o">&lt;</span><span class="kt">u64</span><span class="o">&gt;</span><span class="p">()</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="n">non_fatal_parse_error</span><span class="o">!</span><span class="p">(</span><span class="s">"Failed to parse number: {}"</span><span class="p">,</span><span class="w"> </span><span class="n">token</span><span class="p">);</span><span class="w"></span>
<span class="w">    </span><span class="n">num</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="mi">0</span><span class="p">;</span><span class="w"> </span><span class="c1">// try to recover, to catch more errors in the same run</span>
<span class="p">};</span><span class="w"></span>
</code></pre></div>



<a name="229222564"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229222564" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229222564">(Mar 07 2021 at 22:20)</a>:</h4>
<p>In the diverging case, we could rewrite it as a match or if-let (which would defeat the purpose of <code>let ... else</code> I think), or modify the names to avoid shadowing.</p>
<p>In the non-diverging case, we could rewrite that to use <code>token.parse::&lt;u64&gt;().unwrap_or_else(...)</code>.</p>



<a name="229222652"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229222652" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229222652">(Mar 07 2021 at 22:21)</a>:</h4>
<p><span class="user-mention" data-user-id="138448">@cuviper</span> Do those seem like fair examples to you?</p>



<a name="229223559"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223559" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223559">(Mar 07 2021 at 22:36)</a>:</h4>
<p><span class="user-mention silent" data-user-id="239881">Josh Triplett</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/229222044">said</a>:</p>
<blockquote>
<p><span class="user-mention silent" data-user-id="138448">cuviper</span> <a href="#narrow/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else/near/229221905">said</a>:</p>
<blockquote>
<p>I guess the non-diverging use could <code>match</code> too</p>
</blockquote>
<p>I also suspect the non-diverging case could potentially use <code>unwrap_or</code> or <code>unwrap_or_else</code>, frequently.</p>
</blockquote>
<p>For sure I'm going to be using this for patterns other than Option though, which generally has more than enough combinators to cover all these use cases already. Stuff like <code>let Expr::Add(lhs, rhs) = add_expr else { continue }</code></p>



<a name="229223593"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223593" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223593">(Mar 07 2021 at 22:37)</a>:</h4>
<p>Fair.</p>



<a name="229223635"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223635" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223635">(Mar 07 2021 at 22:38)</a>:</h4>
<p>The question then becomes, do you ever want to <em>not</em> diverge in the else, and instead assign to <code>lhs</code> and <code>rhs</code>?</p>



<a name="229223649"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223649" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223649">(Mar 07 2021 at 22:38)</a>:</h4>
<p>And would that be clearer than using a match or if-let?</p>



<a name="229223685"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223685" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223685">(Mar 07 2021 at 22:39)</a>:</h4>
<p>I wouldn't be bothered much if this didn't support non-divergence at all, there are plenty of other ways to write it if necessary</p>



<a name="229223745"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223745" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223745">(Mar 07 2021 at 22:40)</a>:</h4>
<p>I see the appeal of making the control flow more regular though</p>



<a name="229223805"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223805" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223805">(Mar 07 2021 at 22:41)</a>:</h4>
<p>TBH, I really like the "skimmability" benefit of forced-diverging for these cases.</p>



<a name="229223859"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223859" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223859">(Mar 07 2021 at 22:42)</a>:</h4>
<p>I think there is some readability hazard in having those uninitialized bindings in scope in the else branch</p>



<a name="229223870"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223870" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223870">(Mar 07 2021 at 22:42)</a>:</h4>
<p>there isn't anything in the code that makes that scoping obvious</p>



<a name="229223900"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229223900" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229223900">(Mar 07 2021 at 22:43)</a>:</h4>
<p>It lets the first read ignore the <code>else</code> branch as irrelevant for the code that comes next, like how one can read code in a first pass by not thinking about the <code>?</code>s.</p>
<p>(And it's a really elegant consequence of rust having <code>!</code> in the type system.)</p>



<a name="229224093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224093">(Mar 07 2021 at 22:46)</a>:</h4>
<p>"lets the first read ignore the else branch" is a nice way of putting it.</p>



<a name="229224153"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224153" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224153">(Mar 07 2021 at 22:47)</a>:</h4>
<p>"To a first approximation, make this binding; see the else case for how this code handles the pattern not matching."</p>



<a name="229224224"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224224" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224224">(Mar 07 2021 at 22:48)</a>:</h4>
<p>I do think that exposing the uninitialized bindings in the else case was a really clever idea, though.</p>



<a name="229224240"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224240" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224240">(Mar 07 2021 at 22:48)</a>:</h4>
<p>But on balance, I feel like this will be clearer if we require the <code>else</code> to always diverge, and give it access to whatever the binding <em>would</em> have shadowed if anything.</p>



<a name="229224348"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224348" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224348">(Mar 07 2021 at 22:50)</a>:</h4>
<p>The uninitialized bindings in the <code>else</code> is also nice in that it avoids the temptation to want typestate-like things in</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="w"></span>
<span class="k">else</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="kd">let</span><span class="w"> </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="p">;</span><span class="w"></span>
<span class="w">    </span><span class="n">yeet</span><span class="w"> </span><span class="n">e</span><span class="p">;</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="229224389"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224389" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224389">(Mar 07 2021 at 22:51)</a>:</h4>
<p>should there be a second let-else there?</p>



<a name="229224397"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224397" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Mario Carneiro <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224397">(Mar 07 2021 at 22:52)</a>:</h4>
<p>Oh I see, it's doing the second half of a pattern match</p>



<a name="229224443"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229224443" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229224443">(Mar 07 2021 at 22:52)</a>:</h4>
<p>Scott goes off on a wild tangent idea:<br>
<code>let v = foo?;</code> is</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="nb">Ok</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="n">foo</span><span class="w"></span>
<span class="k">else</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">yeet</span><span class="w"> </span><span class="n">e</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>
<p>(Basically lean into how this is all sugar for a <code>match</code> anyway.  This doesn't trip my usual "I don't want <code>else match</code>" because it's all one construct, so the match can work without needing typestate.)</p>



<a name="229226364"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226364" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226364">(Mar 07 2021 at 23:23)</a>:</h4>
<p>(Aside: this is something fmt-rfcs should make a call on, but I think <code>let ... else</code> should generally be formatted with a hanging else.)</p>



<a name="229226476"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226476" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226476">(Mar 07 2021 at 23:25)</a>:</h4>
<p><span class="user-mention" data-user-id="125270">@scottmcm</span> Doesn't that mean the <code>else match</code> construct still has to implement a kind of typestate in order to implement exhaustiveness checking?</p>



<a name="229226553"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226553" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226553">(Mar 07 2021 at 23:26)</a>:</h4>
<p>Either way, I don't think I'd want to have that; at that point it's no longer clearer than a match, I think.</p>



<a name="229226563"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226563" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226563">(Mar 07 2021 at 23:26)</a>:</h4>
<p>I'm picturing that as one big construct which would desugar to</p>
<div class="codehilite" data-code-language="Rust"><pre><span></span><code><span class="kd">let</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,)</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="k">match</span><span class="w"> </span><span class="n">foo</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">    </span><span class="nb">Ok</span><span class="p">(</span><span class="n">v</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="p">(</span><span class="n">v</span><span class="p">,)</span><span class="w"></span>
<span class="w">    </span><span class="nb">Err</span><span class="p">(</span><span class="n">e</span><span class="p">)</span><span class="w"> </span><span class="o">=&gt;</span><span class="w"> </span><span class="n">yeet</span><span class="w"> </span><span class="n">e</span><span class="p">,</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</code></pre></div>



<a name="229226568"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226568" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226568">(Mar 07 2021 at 23:27)</a>:</h4>
<p>Ah, I see.</p>



<a name="229226592"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226592" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226592">(Mar 07 2021 at 23:27)</a>:</h4>
<p>Is that something you'd want to seriously propose, or a thought experiment you wanted to explore?</p>



<a name="229226828"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226828" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> scottmcm <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226828">(Mar 07 2021 at 23:31)</a>:</h4>
<p>More the latter.</p>
<p>Inspired by the shadowing discussion of whether the original value would be available in <code>let Some(v) = v else {... };</code>, I was thinking what it would look like if someone actually wanted to use that value somehow.</p>
<p>As well as pondering whether there'd be other cases for the "I want the first-read-ignores-the-else" and "it sure would be nice to not have to repeat the bindings" that would be more than binary.  Like if <a href="https://api.rocket.rs/v0.4/rocket/enum.Outcome.html"><code>let Outcome::Success(x) = ...</code></a> might be useful only if the other paths could match their variants.</p>



<a name="229226929"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226929" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226929">(Mar 07 2021 at 23:32)</a>:</h4>
<p>I feel like if the else case cares about knowing that it isn't the case described by the refutable let pattern, that's a good sign to use a match instead.</p>



<a name="229226999"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229226999" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229226999">(Mar 07 2021 at 23:33)</a>:</h4>
<p>If you want to write <code>let Outcome::Success(x) = expr else { diverge with note about expr }</code>, that seems like a good use of <code>let ... else</code>. If the else expression wants to match on <code>expr</code> and you want to avoid having to write something like <code>Outcome::Success =&gt; unreachable!()</code>, use <code>match</code> instead of <code>let ... else</code>.</p>



<a name="229227051"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/213817-t-lang/topic/let%20...%20else/near/229227051" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Josh Triplett <a href="https://rust-lang.github.io/zulip_archive/stream/213817-t-lang/topic/let.20.2E.2E.2E.20else.html#229227051">(Mar 07 2021 at 23:34)</a>:</h4>
<p>I do agree that it <em>could</em> be desugared the way you described though.</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>